In [1]:
SCOPETYPE = 'OPENADC'
PLATFORM = 'CW308_STM32F4'
CRYPTO_TARGET = 'TINYAES128C'
SS_VER = 'SS_VER_2_1'

VERSION = 'HARDWARE'
allowable_exceptions = None
In [2]:
SAVE_REF = False
In [3]:
passed = True
ERR_MSG=""
In [4]:
%%bash -s "$PLATFORM" "$CRYPTO_TARGET" "$SS_VER"
cd ../../firmware/mcu/simpleserial-aes
make PLATFORM=$1 CRYPTO_TARGET=$2 SS_VER=$3
Building for platform CW308\_STM32F4 with CRYPTO\_TARGET=TINYAES128C
SS\_VER set to SS\_VER\_2\_1
.././hal/Makefile.hal:310: *** Missing fw-extra submodule. See https://github.com/newaetech/chipwhisperer-fw-extra.  Stop.
---------------------------------------------------------------------------
CalledProcessError                        Traceback (most recent call last)
Cell In[4], line 1
----> 1 get_ipython().run_cell_magic('bash', '-s "$PLATFORM" "$CRYPTO_TARGET" "$SS_VER"', 'cd ../../firmware/mcu/simpleserial-aes\nmake PLATFORM=$1 CRYPTO_TARGET=$2 SS_VER=$3\n')

File ~/.pyenv/versions/cwtests/lib/python3.10/site-packages/IPython/core/interactiveshell.py:2541, in InteractiveShell.run_cell_magic(self, magic_name, line, cell)
   2539 with self.builtin_trap:
   2540     args = (magic_arg_s, cell)
-> 2541     result = fn(*args, **kwargs)
   2543 # The code below prevents the output from being displayed
   2544 # when using magics with decorator @output_can_be_silenced
   2545 # when the last Python token in the expression is a ';'.
   2546 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):

File ~/.pyenv/versions/cwtests/lib/python3.10/site-packages/IPython/core/magics/script.py:155, in ScriptMagics._make_script_magic.<locals>.named_script_magic(line, cell)
    153 else:
    154     line = script
--> 155 return self.shebang(line, cell)

File ~/.pyenv/versions/cwtests/lib/python3.10/site-packages/IPython/core/magics/script.py:315, in ScriptMagics.shebang(self, line, cell)
    310 if args.raise_error and p.returncode != 0:
    311     # If we get here and p.returncode is still None, we must have
    312     # killed it but not yet seen its return code. We don't wait for it,
    313     # in case it's stuck in uninterruptible sleep. -9 = SIGKILL
    314     rc = p.returncode or -9
--> 315     raise CalledProcessError(rc, cell)

CalledProcessError: Command 'b'cd ../../firmware/mcu/simpleserial-aes\nmake PLATFORM=$1 CRYPTO_TARGET=$2 SS_VER=$3\n'' returned non-zero exit status 2.
In [5]:
#!/usr/bin/env python
# coding: utf-8

# In[ ]:


import chipwhisperer as cw

try:
    if not scope.connectStatus:
        scope.con()
except NameError:
    scope = cw.scope(hw_location=(5, 7))

try:
    if SS_VER == "SS_VER_2_1":
        target_type = cw.targets.SimpleSerial2
    elif SS_VER == "SS_VER_2_0":
        raise OSError("SS_VER_2_0 is deprecated. Use SS_VER_2_1")
    else:
        target_type = cw.targets.SimpleSerial
except:
    SS_VER="SS_VER_1_1"
    target_type = cw.targets.SimpleSerial

try:
    target = cw.target(scope, target_type)
except:
    print("INFO: Caught exception on reconnecting to target - attempting to reconnect to scope first.")
    print("INFO: This is a work-around when USB has died without Python knowing. Ignore errors above this line.")
    scope = cw.scope(hw_location=(5, 7))
    target = cw.target(scope, target_type)


print("INFO: Found ChipWhisperer😍")


# In[ ]:


if "STM" in PLATFORM or PLATFORM == "CWLITEARM" or PLATFORM == "CWNANO":
    prog = cw.programmers.STM32FProgrammer
elif PLATFORM == "CW303" or PLATFORM == "CWLITEXMEGA":
    prog = cw.programmers.XMEGAProgrammer
elif "neorv32" in PLATFORM.lower():
    prog = cw.programmers.NEORV32Programmer
elif PLATFORM == "CW308_SAM4S" or PLATFORM == "CWHUSKY":
    prog = cw.programmers.SAM4SProgrammer
else:
    prog = None


# In[ ]:


import time
time.sleep(0.05)
scope.default_setup()

def reset_target(scope):
    if PLATFORM == "CW303" or PLATFORM == "CWLITEXMEGA":
        scope.io.pdic = 'low'
        time.sleep(0.1)
        scope.io.pdic = 'high_z' #XMEGA doesn't like pdic driven high
        time.sleep(0.1) #xmega needs more startup time
    elif "neorv32" in PLATFORM.lower():
        raise IOError("Default iCE40 neorv32 build does not have external reset - reprogram device to reset")
    elif PLATFORM == "CW308_SAM4S" or PLATFORM == "CWHUSKY":
        scope.io.nrst = 'low'
        time.sleep(0.25)
        scope.io.nrst = 'high_z'
        time.sleep(0.25)
    else:  
        scope.io.nrst = 'low'
        time.sleep(0.05)
        scope.io.nrst = 'high_z'
        time.sleep(0.05)
INFO: Found ChipWhisperer😍
scope.gain.mode                          changed from low                       to high                     
scope.gain.gain                          changed from 0                         to 30                       
scope.gain.db                            changed from 5.5                       to 24.8359375               
scope.adc.basic\_mode                     changed from low                       to rising\_edge              
scope.adc.samples                        changed from 98134                     to 5000                     
scope.adc.trig\_count                     changed from 11216549                  to 22652014                 
scope.clock.adc\_src                      changed from clkgen\_x1                 to clkgen\_x4                
scope.clock.adc\_freq                     changed from 24064693                  to 30067119                 
scope.clock.adc\_rate                     changed from 24064693.0                to 30067119.0               
scope.clock.clkgen\_div                   changed from 1                         to 26                       
scope.clock.clkgen\_freq                  changed from 192000000.0               to 7384615.384615385        
scope.io.tio1                            changed from serial\_tx                 to serial\_rx                
scope.io.tio2                            changed from serial\_rx                 to serial\_tx                
scope.io.hs2                             changed from None                      to clkgen                   
scope.glitch.mmcm\_locked                 changed from True                      to False                    
In [6]:
fw_path = '../../firmware/mcu/simpleserial-aes/simpleserial-aes-{}.hex'.format(PLATFORM)
cw.program_target(scope, prog, fw_path)
Detected known STMF32: STM32F40xxx/41xxx
Extended erase (0x44), this can take ten seconds or more
Attempting to program 6547 bytes at 0x8000000
STM32F Programming flash...
STM32F Reading flash...
Verified flash OK, 6547 bytes
In [7]:
scope.clock.adc_src = "clkgen_x1"
In [8]:
scope.adc.stream_mode = True
In [9]:
scope.adc.basic_mode = "rising_edge"
In [10]:
scope.adc.samples=1000000
In [11]:
ktp = cw.ktp.Basic()
key, text = ktp.next()
ret = cw.capture_trace(scope, target, text, key)
In [12]:
assert len(ret.wave) == 1000000, "Incorrect wave length {}".format(ret.wave)
In [13]:
import numpy as np
if (SAVE_REF):
    np.save("pro_stream.npy", ret.wave)
In [14]:
import numpy as np
ref_wave = np.load("pro_stream.npy", allow_pickle=True)
In [15]:
cw.plot(ret.wave)
Out[15]:
In [16]:
sad = np.sum(np.abs(ref_wave - ret.wave))
#assert(sad < 5000), "Bad stream (must be <5000), SAD = {}".format(sad)
In [17]:
SAD_point = int(120)
scope.adc.stream_mode = False
In [18]:
scope.SAD.reference = ret.wave[SAD_point:SAD_point+128]
In [19]:
scope.SAD.threshold = 2000
In [20]:
scope.SAD.start()
In [21]:
scope.trigger.module = "SAD"
scope.adc.basic_mode = "rising_edge"
In [22]:
scope.adc.samples=5000
In [23]:
from tqdm import tnrange
project = cw.create_project("projects/Tutorial_B5", overwrite = True)
for i in tnrange(100, desc='Capturing traces'):
    key, text = ktp.next()  # manual creation of a key, text pair can be substituted here
    trace = cw.capture_trace(scope, target, text, key)
    if trace is None:
        continue
    project.traces.append(trace)
/tmp/ipykernel\_445459/2914810000.py:3: TqdmDeprecationWarning: Please use \`tqdm.notebook.trange\` instead of \`tqdm.tnrange\`
  for i in tnrange(100, desc='Capturing traces'):
In [24]:
cw.plot(project.waves[1])
Out[24]:
In [25]:
import chipwhisperer.analyzer as cwa
leak_model = cwa.leakage_models.sbox_output
attack = cwa.cpa(project, leak_model)
In [26]:
results = attack.run(None, 100)
In [27]:
print(results)
Subkey KGuess Correlation
  00    0x2B    0.95104
  01    0x7E    0.99168
  02    0x15    0.98832
  03    0x16    0.97448
  04    0x28    0.98751
  05    0xAE    0.99542
  06    0xD2    0.98468
  07    0xA6    0.95680
  08    0xAB    0.98995
  09    0xF7    0.98052
  10    0x15    0.98683
  11    0x88    0.98954
  12    0x09    0.98647
  13    0xCF    0.99276
  14    0x4F    0.98456
  15    0x3C    0.98690

In [28]:
print(results.find_key(), "\n", list(project.keys[0]))
[43, 126, 21, 22, 40, 174, 210, 166, 171, 247, 21, 136, 9, 207, 79, 60] 
 [43, 126, 21, 22, 40, 174, 210, 166, 171, 247, 21, 136, 9, 207, 79, 60]
In [29]:
assert results.find_key() == list(project.keys[0]), "Failed to break key!\nGot: {}\nExp: {}".format(results.find_key(), list(project.keys[0]))
In [ ]: